package org.springblade.modules.admin.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springblade.common.constant.TemplateMsgConstant;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseEntity;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.dto.SimpleElevatorDetailDTO;
import org.springblade.modules.admin.dto.TlwAlarmNoticeDTO;
import org.springblade.modules.admin.dto.TlwBuildingElevatorQuery;
import org.springblade.modules.admin.dto.tlw.TaskStatusDTO;
import org.springblade.modules.admin.dto.tlw.TlwPlanQueryDTO;
import org.springblade.modules.admin.entity.Elevator;
import org.springblade.modules.admin.entity.ElevatorDevice;
import org.springblade.modules.admin.enums.MaintainPlanContentEnum;
import org.springblade.modules.admin.enums.TlwAlarmNoticeEnum;
import org.springblade.modules.admin.mapper.MaintainCheckHistoryMapper;
import org.springblade.modules.admin.service.*;
import org.springblade.modules.admin.vo.*;
import org.springblade.modules.admin.vo.tlw.TlwBuildingVO;
import org.springblade.modules.admin.vo.tlw.TlwByPlanVO;
import org.springblade.modules.admin.vo.tlw.TlwElevatorStatistics;
import org.springblade.modules.system.vo.SimpleUserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Jackey
 * @date 2022年10月13日 14:51
 */
@Service
public class TlwServiceImpl implements TlwService {

	@Value("${project.api.url.estate}")
	private String estateApiUrl;
	@Value("${project.api.url.maintain}")
	private String maintainApiUrl;

	private final String note_push_url = "/tlw/alarm/note/push";
	private final String official_accounts_push_url = "/tlw/alarm/official/accounts/push";
	private final String estate_sms_code = "tlw_estate_push";
	private final String maintain_sms_code = "tlw_repair_push";
	private final String auditor_sms_code = "tlw_auditor_push";

	@Autowired
	private ElevatorDeviceService elevatorDeviceService;
	@Autowired
	private BuildingService buildingService;
	@Autowired
	private IEstateBuildingService estateBuildingService;
	@Autowired
	private ElevatorService elevatorService;
	@Autowired
	private IMaintainPlanContentService planContentService;

	@Autowired
	private UserExtService userExtService;
	@Autowired
	private MaintainMalfunctionLogService malfunctionLogService;

	@Resource
	private MaintainCheckHistoryMapper checkHistoryMapper;

	@Autowired
	private BladeRedis bladeRedis;

	@Override
	public TlwStatisticsVO statistics() {

		TlwStatisticsVO tlwStatisticsVO = new TlwStatisticsVO();

		Integer estateElevatorCount = elevatorDeviceService.count(new LambdaQueryWrapper<ElevatorDevice>().isNotNull(ElevatorDevice::getDeviceId).eq(BaseEntity::getStatus, 1));
		Integer estateBuildingCount = buildingService.estateBuildingCountStatistics();
		Integer estateCompanyCount = estateBuildingService.estateCompanyCountStatistics();
		List<String> deviceList = elevatorDeviceService.deviceList();

		tlwStatisticsVO.setEstateElevatorCount(estateElevatorCount);
		tlwStatisticsVO.setEstateBuildingCount(estateBuildingCount);
		tlwStatisticsVO.setEstateCompanyCount(estateCompanyCount);
		tlwStatisticsVO.setDeviceList(deviceList);

		return tlwStatisticsVO;
	}

	@Override
	public List<TlwRankingListVO> rankingList(List<String> deviceList) {

		return buildingService.rankingList(deviceList);
	}

    @Override
    public List<TlwEstatePeopleVO> estatePeopleList() {

		return userExtService.estatePeopleList();
    }

	@Override
	public Boolean alarmNotice(TlwAlarmNoticeDTO noticeDTO) {
		if(ObjectUtil.isEmpty(noticeDTO.getDeviceId())){
			throw new ServiceException("[deviceId] 设备id不可为空");
		}
		if(ObjectUtil.isEmpty(noticeDTO.getPushChannelTypeList())){
			throw new ServiceException("[pushChannelType] 推送渠道类型不可为空");
		}
		if(ObjectUtil.isEmpty(noticeDTO.getPushPeopleTypeList())){
			throw new ServiceException("[pushPeopleTypeList] 推送对象类型不可为空");
		}
		ElevatorDevice elevatorDevice = elevatorDeviceService.getOne(Wrappers.<ElevatorDevice>lambdaQuery().eq(ElevatorDevice::getDeviceId,noticeDTO.getDeviceId()),false);
		if(ObjectUtil.isNotEmpty(elevatorDevice) && ObjectUtil.isNotEmpty(elevatorDevice.getElevatorId())){
			noticeDTO.getPushPeopleTypeList().forEach(p -> {
				SimpleElevatorDetailDTO simpleElev = elevatorDeviceService.getSimpleElevator(elevatorDevice.getElevatorId(),p);
				if(ObjectUtil.isNotEmpty(simpleElev)){
					List<SimpleUserVO> userList;
					if(p.equals(TlwAlarmNoticeEnum.PEOPLE_TYPE.ESTATE.getId())){
						if(ObjectUtil.isNotEmpty(noticeDTO.getEstateUserIdList())){
							userList = elevatorDeviceService.getSimpleUserByUserId(noticeDTO.getEstateUserIdList());
							userList.forEach(u -> {
								noticeDTO.getPushChannelTypeList().forEach(e -> {
									if(e.equals(TlwAlarmNoticeEnum.CHANNEL_TYPE.NOTE.getId())){
										HashMap<String,Object> map = new HashMap<>(3);
										HashMap<String,String> smsMap = new HashMap<>(5);
										smsMap.put("estateCompanyName",simpleElev.getEstateTenantName());
										smsMap.put("elevatorName",simpleElev.getBuildingName()+simpleElev.getElevatorAddress());
										smsMap.put("alarmTime",noticeDTO.getPushContentDTO().getAlarmTime());
										smsMap.put("alarmFloor",noticeDTO.getPushContentDTO().getAlarmFloor());
										smsMap.put("alarmName",noticeDTO.getPushContentDTO().getAlarmName());
										map.put("phone",u.getPhone());
										map.put("params",smsMap);
										map.put("smsCode",estate_sms_code);
										// redis根据消息code + 用户电话 + 状态作为key值
										String key = u.getPhone() + estate_sms_code;
										//如果不存在key则发送消息
										if (!bladeRedis.exists(key)) {
											bladeRedis.setEx(key, UUID.randomUUID().toString(), Duration.ofSeconds(60L));
											HttpUtil.createPost(estateApiUrl + note_push_url).body(JSONObject.toJSONString(map)).execute().body();
										}
									}else if(e.equals(TlwAlarmNoticeEnum.CHANNEL_TYPE.PHONE.getId())){
										//todo 电话待定
									}else if(e.equals(TlwAlarmNoticeEnum.CHANNEL_TYPE.OFFICIAL_ACCOUNTS.getId())){
										if(ObjectUtil.isNotEmpty(u.getOpenid())){
											HashMap<String,Object> map = new HashMap<>(3);
											HashMap<String,String> templateMap = new HashMap<>(5);
											templateMap.put("first","预警提醒");
											templateMap.put("keyword1",noticeDTO.getPushContentDTO().getAlarmName());
											templateMap.put("keyword2",noticeDTO.getPushContentDTO().getAlarmTime());
											templateMap.put("remark","请及时处理");
											templateMap.put("params","packPage/myElevators/myCallPoliceDetail?scoreState=1&id="+noticeDTO.getPushContentDTO().getAlarmId()
												+"&elevatorId="+simpleElev.getElevatorId()+"&playStartType="+noticeDTO.getPlayStartType());
											map.put("openid",u.getOpenid());
											map.put("params",templateMap);
											map.put("templateId", TemplateMsgConstant.TLW_ALARM_ESTATE_PUSH_ID);
											// redis根据消息code + 用户opendid + 状态作为key值
											String key = u.getOpenid() + TemplateMsgConstant.TLW_ALARM_ESTATE_PUSH_ID;
											//如果不存在key则发送消息
											if (!bladeRedis.exists(key)) {
												bladeRedis.setEx(key, UUID.randomUUID().toString(), Duration.ofSeconds(60L));
												HttpUtil.createPost(estateApiUrl+official_accounts_push_url).body(JSONObject.toJSONString(map)).execute().body();
											}
										}
									}
								});
							});
						}
					}else if(p.equals(TlwAlarmNoticeEnum.PEOPLE_TYPE.MAINTAIN.getId())) {
						userList = elevatorDeviceService.getSimpleUserByDeviceId(noticeDTO.getDeviceId());
						userList.forEach(u -> {
							noticeDTO.getPushChannelTypeList().forEach(e -> {
								if(e.equals(TlwAlarmNoticeEnum.CHANNEL_TYPE.NOTE.getId())){
									HashMap<String,Object> map = new HashMap<>(3);
									HashMap<String,String> smsMap = new HashMap<>(5);
									smsMap.put("repairPeopleName",u.getUserName());
									smsMap.put("elevatorName",simpleElev.getBuildingName()+simpleElev.getElevatorAddress());
									smsMap.put("alarmTime",noticeDTO.getPushContentDTO().getAlarmTime());
									smsMap.put("alarmFloor",noticeDTO.getPushContentDTO().getAlarmFloor());
									smsMap.put("alarmName",noticeDTO.getPushContentDTO().getAlarmName());
									map.put("phone",u.getPhone());
									map.put("params",smsMap);
									map.put("smsCode",maintain_sms_code);
									// redis根据消息code + 用户电话 + 状态作为key值
									String key = u.getPhone() + maintain_sms_code;
									//如果不存在key则发送消息
									if (!bladeRedis.exists(key)) {
										bladeRedis.setEx(key, UUID.randomUUID().toString(), Duration.ofSeconds(60L));
										HttpUtil.createPost(maintainApiUrl+note_push_url).body(JSONObject.toJSONString(map)).execute().body();
									}
								}else if(e.equals(TlwAlarmNoticeEnum.CHANNEL_TYPE.PHONE.getId())){
									//todo 电话待定
								}else if(e.equals(TlwAlarmNoticeEnum.CHANNEL_TYPE.OFFICIAL_ACCOUNTS.getId())){
									if(ObjectUtil.isNotEmpty(u.getOpenid()) && ObjectUtil.isNotEmpty(u.getSubscribe()) && u.getSubscribe().equals(1)){
										HashMap<String,Object> map = new HashMap<>(3);
										HashMap<String,String> templateMap = new HashMap<>(7);
										templateMap.put("first",String.format("维保员%s您好！",u.getUserName()));
										templateMap.put("keyword1",noticeDTO.getPushContentDTO().getAlarmType());
										templateMap.put("keyword2",noticeDTO.getPushContentDTO().getAlarmTime());
										templateMap.put("keyword3",simpleElev.getBuildingName()+simpleElev.getElevatorAddress());
										templateMap.put("keyword4",noticeDTO.getPushContentDTO().getAlarmName());
										templateMap.put("keyword5","梯联网AI盒子");
										templateMap.put("remark","请及时确认处理。希道梯无忧祝您工作顺利！");
										map.put("openid",u.getOpenid());
										map.put("params",templateMap);
										map.put("templateId", TemplateMsgConstant.TLW_ALARM_MAINTAIN_PUSH_ID);
										// redis根据消息code + 用户opendid + 状态作为key值
										String key = u.getOpenid() + TemplateMsgConstant.TLW_ALARM_MAINTAIN_PUSH_ID;
										//如果不存在key则发送消息
										if (!bladeRedis.exists(key)) {
											bladeRedis.setEx(key, UUID.randomUUID().toString(), Duration.ofSeconds(60L));
											HttpUtil.createPost(maintainApiUrl+official_accounts_push_url).body(JSONObject.toJSONString(map)).execute().body();
										}
									}
								}
							});
						});
					}if(p.equals(TlwAlarmNoticeEnum.PEOPLE_TYPE.ASSESSOR.getId())){
						// 负责人暂定写死
						if(ObjectUtil.isNotEmpty(noticeDTO.getAssessorPhones())){
							userList = elevatorDeviceService.getSimpleUserByPhone(noticeDTO.getAssessorPhones());
							List<SimpleUserVO> finalUserList = userList;
							noticeDTO.getPushChannelTypeList().forEach(e -> {
								if(e.equals(TlwAlarmNoticeEnum.CHANNEL_TYPE.NOTE.getId())){
									noticeDTO.getAssessorPhones().forEach(u -> {
										HashMap<String,Object> map = new HashMap<>(3);
										HashMap<String,String> smsMap = new HashMap<>(5);
										smsMap.put("alarmCount",noticeDTO.getPushContentDTO().getAuditorPushMsg());
										map.put("phone",u);
										map.put("params",smsMap);
										map.put("smsCode",auditor_sms_code);
										// redis根据消息code + 用户电话 + 状态作为key值
										String key = u + auditor_sms_code;
										//如果不存在key则发送消息
										if (!bladeRedis.exists(key)) {
											bladeRedis.setEx(key, UUID.randomUUID().toString(), Duration.ofSeconds(60L));
											HttpUtil.createPost(maintainApiUrl+note_push_url).body(JSONObject.toJSONString(map)).execute().body();
										}
									});
								}else if(e.equals(TlwAlarmNoticeEnum.CHANNEL_TYPE.PHONE.getId())){
									//todo 电话待定
								}else if(e.equals(TlwAlarmNoticeEnum.CHANNEL_TYPE.OFFICIAL_ACCOUNTS.getId())){
									finalUserList.forEach(u -> {
										if(ObjectUtil.isNotEmpty(u.getOpenid())){
											HashMap<String,Object> map = new HashMap<>(3);
											HashMap<String,String> templateMap = new HashMap<>(7);
											templateMap.put("first",String.format("梯联网运维%s您好！",u.getUserName()));
											templateMap.put("keyword1",noticeDTO.getPushContentDTO().getAlarmType());
											templateMap.put("keyword2",noticeDTO.getPushContentDTO().getAlarmTime());
											templateMap.put("keyword3",simpleElev.getBuildingName()+simpleElev.getElevatorAddress());
											templateMap.put("keyword4",noticeDTO.getPushContentDTO().getAlarmName());
											templateMap.put("keyword5","梯联网AI盒子");
											templateMap.put("remark","请及时确认处理。希道梯无忧祝您工作顺利！");
											map.put("openid",u.getOpenid());
											map.put("params",templateMap);
											map.put("templateId", TemplateMsgConstant.TLW_ALARM_MAINTAIN_PUSH_ID);
											// redis根据消息code + 用户opendid + 状态作为key值
											String key = u.getOpenid() + TemplateMsgConstant.TLW_ALARM_MAINTAIN_PUSH_ID;
											//如果不存在key则发送消息
											if (!bladeRedis.exists(key)) {
												bladeRedis.setEx(key, UUID.randomUUID().toString(), Duration.ofSeconds(60L));
												HttpUtil.createPost(maintainApiUrl+official_accounts_push_url).body(JSONObject.toJSONString(map)).execute().body();
											}
										}
									});
								}
							});
						}
					}
				}
			});
		}
		return Boolean.TRUE;
	}

	@Override
	public List<TlwEstatePeopleVO> maintainPeopleList(String deviceId) {
		List<TlwEstatePeopleVO> peopleVOS = new ArrayList<>();
		List<SimpleUserVO> userVOS = elevatorDeviceService.getSimpleUserByDeviceId(deviceId);
		if(ObjectUtil.isNotEmpty(userVOS)){
			peopleVOS = userVOS.stream().map(e -> {
				TlwEstatePeopleVO peopleVO = new TlwEstatePeopleVO();
				peopleVO.setId(e.getUserId());
				peopleVO.setRealName(e.getUserName());
				peopleVO.setPhone(e.getPhone());
				return peopleVO;
			}).collect(Collectors.toList());
		}
		return peopleVOS;
	}

	@Override
	public List<BuildingDeviceEleVO> buildingDeviceEleList(Long buildingId) {
		return elevatorDeviceService.buildingDeviceEleList(buildingId);
	}

	@Override
	public List<Map<String, Object>> batchMaintainPeopleList(String deviceIds) {
		if(ObjectUtil.isEmpty(deviceIds)){
			throw new ServiceException("deviceIds 不可为空");
		}
		List<Map<String,Object>> result = elevatorDeviceService.getSimpleUserByDeviceIds(Func.toStrList(deviceIds));
		return result;
	}

	@Override
	public Map<String, Object> buildingElevatorPage(TlwBuildingElevatorQuery tbeQuery, Query query) {
		Map<String,Object> resultMap = buildingService.tlwBuildingElevatorCount(tbeQuery);
		IPage<TlwBuildingVO> buildingPage = buildingService.selectTlwBuildingElevatorPage(tbeQuery, Condition.getPage(query));
		resultMap.put("page",buildingPage);
		return resultMap;
	}

	@Override
	public Map<String, Object> deviceBuildingElevatorPage(TlwBuildingElevatorQuery tbeQuery, Query query) {
		List<ElevatorDevice> elevatorDevices = elevatorDeviceService.list();
		if(ObjectUtil.isNotEmpty(elevatorDevices)){
			List<Long> elevatorIds = elevatorDevices.stream().map(ElevatorDevice::getElevatorId).collect(Collectors.toList());
			List<Elevator> elevators = elevatorService.listByIds(elevatorIds);
			if(ObjectUtil.isNotEmpty(elevators)){
				tbeQuery.setBuildingIds(elevators.stream().map(Elevator::getBuildingId).collect(Collectors.toList()));
				tbeQuery.setElevatorIds(elevators.stream().map(Elevator::getId).collect(Collectors.toList()));
			}
		}
		return this.buildingElevatorPage(tbeQuery,query);
	}

	@Override
	public List<Map<String, Object>> batchElevatorMaintainPeopleList(String elevatorIds) {
		if(ObjectUtil.isEmpty(elevatorIds)){
			throw new ServiceException("elevatorIds 不可为空");
		}
		List<Map<String,Object>> result = elevatorDeviceService.getSimpleUserByElevatorIds(Func.toLongList(elevatorIds));
		return result;
	}

	@Override
	public IPage<TlwByPlanVO> tlwByPlanPage(TlwPlanQueryDTO queryDTO, IPage<TlwByPlanVO> page) {
		List<TlwByPlanVO> planPage = planContentService.tlwByPlanPage(queryDTO,page);
		return page.setRecords(planPage);
	}

	@Override
	public List<TlwByPlanVO> tlwByPlanList(TlwPlanQueryDTO queryDTO) {
		List<TlwByPlanVO> planList = planContentService.tlwByPlanList(queryDTO);
		return planList;
	}

	@Override
	public TlwByPlanVO tlwByPlanDetail(Long planId) {
		TlwByPlanVO planDetail = planContentService.tlwByPlanDetail(planId);
		WorkTrackVO workTrack = malfunctionLogService.selectWorkTracks(planId);
		planDetail.setWorkTrack(workTrack);
		return planDetail;
	}

	@Override
	public List<PlanTemplateVO> getPlanWorkItem(Long planId, Long templateId,Integer isStore) {
		List<PlanTemplateVO> planCheckHistoryList = checkHistoryMapper.listPlanHistory(planId, templateId, isStore, AuthUtil.getTenantId());
		planCheckHistoryList.forEach(e -> {
			e = disposePlanTemplateType(e, planId);
			e.setTemplateContentVOS(null);
		});
		return planCheckHistoryList;
	}

	/**
	 * 封装模板分类及对应工作项
	 *
	 * @param planTemplateVO
	 * @return
	 */
	private PlanTemplateVO disposePlanTemplateType(PlanTemplateVO planTemplateVO, Long planId) {
		List<PlanTemplateContentVO> templateContentVOS = planTemplateVO.getTemplateContentVOS();
		List<PlanTemplateTypeVO> templateTypeVOS = getTypeZeroList(templateContentVOS);
		for (PlanTemplateContentVO t : templateContentVOS) {
			// 封装模板分类Tree
			List<String> tltIds = Func.toStrList(t.getTltIds());
			List<String> tltIdName = Func.toStrList("&&", t.getTltNames());
			if (tltIds.size() > 1) {
				for (int i = 1; i < tltIds.size(); i++) {
					templateTypeVOS = changeHistory(templateTypeVOS, Long.valueOf(tltIds.get(i)), tltIdName.get(i), Long.valueOf(tltIds.get(i - 1)));
				}
			}
		}
		// 封装对应工作项
		templateTypeVOS = changeHistoryContent(templateTypeVOS, templateContentVOS);
		templateTypeVOS.forEach(e -> {
			e = doCount(e, new HashMap<>());
		});
		planTemplateVO.setTemplateTypeVOS(templateTypeVOS);
		return planTemplateVO;
	}

	/**
	 * 封装任务历史数据分类Tree根节点
	 *
	 * @param templateContentVOS
	 * @return
	 */
	private List<PlanTemplateTypeVO> getTypeZeroList(List<PlanTemplateContentVO> templateContentVOS) {
		List<PlanTemplateTypeVO> planTemplateTypeVOS = templateContentVOS.stream().map(e -> {
			List<String> tltIds = Func.toStrList(e.getTltIds());
			List<String> tltIdName = Func.toStrList("&&", e.getTltNames());
			PlanTemplateTypeVO planTemplateTypeVO = new PlanTemplateTypeVO();
			planTemplateTypeVO.setTltId(Long.valueOf(tltIds.get(0)));
			planTemplateTypeVO.setTltName(tltIdName.get(0));
			planTemplateTypeVO.setTltParentId(0L);
			return planTemplateTypeVO;
		}).collect(Collectors.toList());
		planTemplateTypeVOS = planTemplateTypeVOS.stream().collect(Collectors.collectingAndThen(
			Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(e -> e.getTltId() + ";" + e.getTltName()))), ArrayList::new
		));
		return planTemplateTypeVOS;
	}

	/**
	 * 封装历史对应工作项分类数据
	 *
	 * @param planTemplateTypeVOS
	 * @param tltId
	 * @return
	 */
	private List<PlanTemplateTypeVO> changeHistory(List<PlanTemplateTypeVO> planTemplateTypeVOS, Long tltId, String tltName, Long parentId) {
		planTemplateTypeVOS.forEach(e -> {
			if (e.getTltId().equals(parentId)) {
				List<PlanTemplateTypeVO> children = e.getChildren();
				if (ObjectUtil.isEmpty(children)) {
					children = new ArrayList<>();
				}
				PlanTemplateTypeVO planTemplateTypeVO = new PlanTemplateTypeVO();
				planTemplateTypeVO.setTltId(tltId);
				planTemplateTypeVO.setTltName(tltName);
				planTemplateTypeVO.setTltParentId(parentId);
				children.add(planTemplateTypeVO);
				children = children.stream().collect(Collectors.collectingAndThen(
					Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(j -> j.getTltId() + ";" + j.getTltName()))), ArrayList::new
				));
				e.setChildren(children);
			} else {
				if (ObjectUtil.isNotEmpty(e.getChildren())) {
					changeHistory(e.getChildren(), tltId, tltName, parentId);
				}
			}
		});
		return planTemplateTypeVOS;
	}

	/**
	 * 封装历史记录对应工作项
	 *
	 * @param templateTypeVOS 分类tree集合
	 * @return
	 */
	private List<PlanTemplateTypeVO> changeHistoryContent(List<PlanTemplateTypeVO> templateTypeVOS, List<PlanTemplateContentVO> templateContentVOS) {
		templateTypeVOS.forEach(e -> {
			if (ObjectUtil.isEmpty(e.getChildren())) {
				templateContentVOS.forEach(j -> {
					List<String> tltIds = Func.toStrList(j.getTltIds());
					if (e.getTltId().equals(Long.valueOf(tltIds.get(tltIds.size() - 1)))) {
						List<PlanTemplateContentVO> planTemplateContentVOS = e.getPlanTemplateContentVOS();
						if (ObjectUtil.isEmpty(planTemplateContentVOS)) {
							planTemplateContentVOS = new ArrayList<>();
						}
						planTemplateContentVOS.add(j);
						e.setPlanTemplateContentVOS(planTemplateContentVOS);
					}
				});
			} else {
				changeHistoryContent(e.getChildren(), templateContentVOS);
			}
		});
		return templateTypeVOS;
	}

	/**
	 * 树形结构展示的某个节点的统计数值=所有子节点工作项数量总和
	 *
	 * @param root
	 * @param result
	 * @return
	 */
	public static PlanTemplateTypeVO doCount(PlanTemplateTypeVO root, Map<String, Object> result) {
		int count = 0;
		List<PlanTemplateTypeVO> list = root.getChildren();
		if (ObjectUtil.isEmpty(list)) {
			count = root.getPlanTemplateContentVOS().size();
			root.setWorkItemCount(count);
			return root;
		}

		for (PlanTemplateTypeVO child : list) {
			//统计子节点的孩子总数
			int cur_cnt = doCount(child, result).getWorkItemCount();
			result.put(String.valueOf(child.getTltId()), cur_cnt);
			count += cur_cnt;
			root.setWorkItemCount(count);
		}

		//返回前记录当前节点的统计个数
		result.put(String.valueOf(root.getTltId()), count);
		return root;
	}

	@Override
	public List<ElevatorTaskStatusVO> getElevatorTaskStatusList(TaskStatusDTO taskStatusDTO) {
		List<ElevatorTaskStatusVO> taskStatusList = planContentService.getElevatorTaskStatusList(taskStatusDTO.getDeviceIds());
		return taskStatusList;
	}

	@Override
	public TlwElevatorStatistics getElevatorStatistics(String deviceId, Long startAt, Long endAt) {
		TlwElevatorStatistics statistics = new TlwElevatorStatistics();
		List<MaintainPlanContentVO> list = planContentService.getTlwElevatorStatistics(deviceId, DateUtil.date(startAt), DateUtil.date(endAt));
		// 故障停梯总时间（分钟）
		long stopTimeMin = list.stream().filter(t -> t.getTypeStatus() == MaintainPlanContentEnum.MAINTAIN_WX.getId() && t.getPlanCreateTime() != null  && t.getPlanEndTime() != null)
			.collect(Collectors.summingLong(t -> DateUtil.between(t.getPlanCreateTime(), t.getPlanEndTime(), DateUnit.MINUTE)));
		statistics.setStopTimeMin(stopTimeMin);

		// 故障总次数
		long malTotal = list.stream().filter(t -> t.getTypeStatus() == MaintainPlanContentEnum.MAINTAIN_WX.getId()).count();
		statistics.setMalTotal(malTotal);

		// 困人总次数
		long rescueTotal = list.stream().filter(t -> t.getTypeStatus() == MaintainPlanContentEnum.MAINTAIN_KR.getId()).count();
		statistics.setRescueTotal(rescueTotal);

		return statistics;
	}
}
